package com.ruoyi.system.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.constants.TenantConstants;
import com.ruoyi.system.domain.SysRoleDept;
import com.ruoyi.system.domain.SysTenant;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysTenantService;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;

/**
 * 租户管理Service业务层处理
 *
 * @author likun
 * @date 2020-09-19
 */
@Service
public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenant> implements ISysTenantService {

    @Autowired
    private SysTenantMapper sysTenantMapper;
    @Autowired
    private SysDeptMapper deptMapper;
    @Autowired
    private SysMenuMapper menuMapper;
    @Autowired
    private SysRoleMapper roleMapper;
    @Autowired
    private SysRoleDeptMapper roleDeptMapper;
    @Autowired
    private SysRoleMenuMapper roleMenuMapper;
    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    private SysUserRoleMapper userRoleMapper;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private ISysRoleService roleService;

    /**
     * 查询租户管理列表
     *
     * @param sysTenant 租户管理
     * @return 租户管理
     */
    @Override
    public List<SysTenant> selectSysTenantList(SysTenant sysTenant) {
        return sysTenantMapper.selectSysTenantList(sysTenant);
    }

    /**
     * 新增租户
     * 添加租户时同时初始化数据
     * 1.创建该租户的根部门。
     * 2.创建该租户的管理员角色。
     * 3.创建该租户的管理员用户。
     * 4.为该用户绑定部门和管理员角色。
     * 5.绑定角色和部门。
     *
     * @param sysTenant 租户管理
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public int insertSysTenant(SysTenant sysTenant) {
        //校验用户名、手机号、邮箱
        if (UserConstants.NOT_UNIQUE.equals(checkLoginNameUnique(sysTenant.getUserName()))) {
            return 0;
        }
        if (UserConstants.NOT_UNIQUE.equals(checkMobileUnique(sysTenant))) {
            return 0;
        }
        if (UserConstants.NOT_UNIQUE.equals(checkEmailUnique(sysTenant))) {
            return 0;
        }
        sysTenant.setPassword(SecurityUtils.encryptPassword(sysTenant.getPassword()));
        sysTenant.setCreateBy(SecurityUtils.getUsername());
        sysTenant.setCreateTime(DateUtils.getNowDate());
        sysTenantMapper.insert(sysTenant);

        SysDept sysDept = initDept(sysTenant);
        sysTenant.setDeptId(sysDept.getDeptId());
        SysRole sysRole = initRole(sysTenant);
        sysTenant.setRoleId(sysRole.getRoleId());
        SysUser sysUser = initUser(sysTenant);
        sysTenant.setUserId(sysUser.getUserId());

        //更新初始化的id到租户表.
        sysTenantMapper.updateById(sysTenant);

        //插入角色部门对应关系并修改租户id
        SysRoleDept sysRoleDept = new SysRoleDept();
        sysRoleDept.setRoleId(sysRole.getRoleId());
        sysRoleDept.setDeptId(sysDept.getDeptId());
        roleDeptMapper.batchRoleDept(Arrays.asList(sysRoleDept));

        //插入用户角色对应关系并修改租户id
        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setUserId(sysUser.getUserId());
        sysUserRole.setRoleId(sysRole.getRoleId());
        userRoleMapper.batchUserRole(Arrays.asList(sysUserRole));

        return 1;
    }

    private SysDept initDept(SysTenant sysTenant) {
        //初始化部门数据
        SysDept sysDept = new SysDept();
        sysDept.setDeptName(sysTenant.getCompany());
        sysDept.setOrderNum("1");
        sysDept.setParentId(0L);
        sysDept.setAncestors("0");
        sysDept.setLeader(sysTenant.getNickName());
        sysDept.setPhone(sysTenant.getMobile());
        sysDept.setEmail(sysTenant.getEmail());
        sysDept.setStatus("0");
        sysDept.setDelFlag("0");
        sysDept.setCreateBy(SecurityUtils.getUsername());
        sysDept.setCreateTime(DateUtils.getNowDate());
        sysDept.setRemark("租户创建-初始化部门");
        deptMapper.insertDept(sysDept);

        sysDept.setTenantId(sysTenant.getId());
        sysTenantMapper.updateDeptTenant(sysDept);
        return sysDept;
    }

    private SysRole initRole(SysTenant sysTenant) {
        //初始化角色
        SysRole sysRole = new SysRole();
        sysRole.setRoleKey("admin");
        sysRole.setRoleName("管理员");
        sysRole.setMenuCheckStrictly(true);
        sysRole.setDeptCheckStrictly(true);
        sysRole.setRoleSort("1");
        sysRole.setDataScope("1");
        sysRole.setStatus("0");
        sysRole.setDelFlag("0");
        sysRole.setCreateBy(SecurityUtils.getUsername());
        sysRole.setCreateTime(DateUtils.getNowDate());
        sysRole.setRemark("租户创建-初始化角色");
        roleMapper.insertRole(sysRole);

        sysRole.setTenantId(sysTenant.getId());
        sysTenantMapper.updateRoleTenant(sysRole);
        return sysRole;
    }

    private SysUser initUser(SysTenant sysTenant) {
        //初始化管理员用户
        SysUser sysUser = new SysUser();
        sysUser.setDeptId(sysTenant.getDeptId());
        sysUser.setUserName(sysTenant.getUserName());
        sysUser.setPassword(sysTenant.getPassword());
        sysUser.setSalt(sysTenant.getSalt());
        sysUser.setPhonenumber(sysTenant.getMobile());
        sysUser.setEmail(sysTenant.getEmail());
        sysUser.setNickName(sysTenant.getNickName());
        sysUser.setSex("2");
        sysUser.setStatus("0");
        sysUser.setDelFlag("0");
        sysUser.setCreateBy(SecurityUtils.getUsername());
        sysUser.setCreateTime(DateUtils.getNowDate());
        sysUser.setRemark("租户创建-初始化管理员用户");
        userMapper.insertUser(sysUser);

        sysUser.setTenantId(sysTenant.getId());
        sysTenantMapper.updateUserTenant(sysUser);
        return sysUser;
    }


    /**
     * 修改租户管理
     *
     * @param sysTenant 租户管理
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public int updateSysTenant(SysTenant sysTenant) {
        sysTenant.setPassword(SecurityUtils.encryptPassword(sysTenant.getPassword()));

        sysTenant.getUserName();
        SysUser sysUser = userService.selectUserById(sysTenant.getUserId());
        sysUser.setPassword(sysTenant.getPassword());
        sysUser.setNickName(sysTenant.getNickName());
        sysUser.setUserName(sysTenant.getUserName());
        sysUser.setPhonenumber(sysTenant.getMobile());
        userService.updateUser(sysUser);

        sysTenant.setUpdateTime(DateUtils.getNowDate());
        return sysTenantMapper.updateById(sysTenant);
    }

    /**
     * 删除租户对象
     * 提醒用户慎重删除，逻辑删除租户和逻辑删除该租户下的所有用户数据。
     *
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteSysTenantByIds(Long[] ids) {
        for (Long tenantId : ids) {
            deleteSysTenantById(tenantId);
        }
        return 1;
    }

    /**
     * 删除租户对象
     * 提醒用户慎重删除，逻辑删除租户和逻辑删除该租户下的所有用户数据。
     *
     * @param tenantId 租户管理ID
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public int deleteSysTenantById(Long tenantId) {
        //删除该租户下所有用户
        sysTenantMapper.deleteUsersByTenantId(tenantId);
        //删除该租户下所有角色
        sysTenantMapper.deleteRolesByTenantId(tenantId);
        //删除该租户下所有部门
        sysTenantMapper.deleteDeptsByTenantId(tenantId);
        //删除租户
        return sysTenantMapper.deleteById(tenantId);
    }

    /**
     * 修改密码
     * 同时重置租户中保存的密码和用户表中保存的密码，因为此密码用于登录。
     * 用户表中的用户修改密码不影响租户表中的密码。
     *
     * @param tenant 租户信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public int resetUserPwd(SysTenant tenant) {

        tenant.setPassword(SecurityUtils.encryptPassword(tenant.getPassword()));
        SysTenant dbTenant = sysTenantMapper.selectById(tenant.getId());
        if (dbTenant != null) {
            //修改用户登录密码
            SysUser sysUser = userMapper.selectUserById(dbTenant.getUserId());
            if (sysUser != null) {
                sysUser.setPassword(tenant.getPassword());
                userMapper.updateUser(sysUser);
            }
        }

        return sysTenantMapper.updateById(tenant);
    }

    /**
     * 校验登录名称是否唯一
     *
     * @param loginName 用户名
     * @return
     */
    @Override
    public String checkLoginNameUnique(String loginName) {
        //校验租户表
        int count = sysTenantMapper.checkUserNameUnique(loginName);
        if (count > 0) {
            return TenantConstants.TENANT_NAME_NOT_UNIQUE;
        }
        //校验用户表
        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(loginName))) {
            return TenantConstants.TENANT_NAME_NOT_UNIQUE;
        }
        return TenantConstants.TENANT_NAME_UNIQUE;
    }

    /**
     * 校验用户名称是否唯一
     *
     * @param tenant 用户信息
     * @return
     */
    @Override
    public String checkMobileUnique(SysTenant tenant) {
        //校验租户表
        Long id = StringUtils.isNull(tenant.getId()) ? -1L : tenant.getId();
        SysTenant info = sysTenantMapper.checkMobileUnique(tenant.getMobile());
        if (StringUtils.isNotNull(info) && info.getId().longValue() != id.longValue()) {
            return TenantConstants.TENANT_PHONE_NOT_UNIQUE;
        }

        //校验用户表
        SysUser sysUser = new SysUser();
        sysUser.setPhonenumber(tenant.getMobile());
        if (UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(sysUser))) {
            return TenantConstants.TENANT_PHONE_NOT_UNIQUE;
        }
        return TenantConstants.TENANT_PHONE_UNIQUE;
    }

    /**
     * 校验email是否唯一
     *
     * @param tenant 用户信息
     * @return
     */
    @Override
    public String checkEmailUnique(SysTenant tenant) {
        //校验租户表
        Long id = StringUtils.isNull(tenant.getId()) ? -1L : tenant.getId();
        SysTenant info = sysTenantMapper.checkEmailUnique(tenant.getEmail());
        if (StringUtils.isNotNull(info) && info.getId().longValue() != id.longValue()) {
            return TenantConstants.TENANT_EMAIL_NOT_UNIQUE;
        }

        //校验用户表
        SysUser sysUser = new SysUser();
        sysUser.setEmail(tenant.getEmail());
        if (UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(sysUser))) {
            return TenantConstants.TENANT_EMAIL_NOT_UNIQUE;
        }
        return TenantConstants.TENANT_EMAIL_UNIQUE;
    }

    /**
     * 为租户进行菜单授权：
     * 1.界面添加按钮选择为该租户开通哪些菜单。
     * 2.开通的菜单和该租户管理员角色绑定在一起。
     *
     * @param sysTenant 租户
     * @param menuIds   菜单
     * @return 结果
     */
    @Override
    public int grantAuthSave(SysTenant sysTenant, Long[] menuIds) {

        //更新初始角色与所选择的菜单的进行授权.
        SysRole sysRole = new SysRole();
        sysRole.setRoleId(sysTenant.getRoleId());
        sysRole.setMenuIds(menuIds);
        roleService.updateRole(sysRole);

        return 1;
    }
}
